﻿#include "ais_pointcloud.h"
#include "ais_point.h"
#include "kernel/transform.h"

CAGD::AIS_PointCloud::AIS_PointCloud(const std::vector<BPnt> &points) : m_points(points)
{
    // 设置属性
    m_info.smooth = true;
    m_info.psize = 3;

    // 创建子节点包围盒
    auto box = Handle(AIS_Box)(new AIS_Box);
    AddChild(box);
    box->UpdateArray();
    m_context.CreateObject(box);

    // 创建质心点，孤立质心点
    m_info.centroid = box->GetBBox().center;
    m_info._centroid = m_info.centroid;
    Handle(GeomPoint) center(new GeomPoint(&m_info.centroid));
    Handle(AIS_Point) c(new AIS_Point(center));
    if (m_context.GetInfo().viewMode != ViewMode::CONTROL)
        c->GetInfo().status = AIS_Status::HIDDEN;
    c->GetInfo().smooth = true;
    c->GetInfo().psize = 10;

    m_context.CreateObject(c);
}

bool CAGD::AIS_PointCloud::MoveTo(Point pos)
{
    // 隐藏状态不交互，不活跃状态不交互
    if (m_info.status == AIS_Status::HIDDEN || m_info.active == false)
        return false;

    bool hang = false;
    auto tmp = m_info.status;
    m_info.status = AIS_Status::NONE;

    auto box = dynamic_cast<AIS_Box *>(GetChild(AIS_Type::BOX));
    if (box->Collision(pos))
    {
        float d;
        auto p = box->GetBBox().center;
        m_context.GetScreenPoint(p, d);

        SetDepth(d);
        hang = true;

        if (tmp != AIS_Status::TOUCH)
            m_info.status = AIS_Status::HANG;
        else
            m_info.status = tmp;
    }
    return hang;
}

void CAGD::AIS_PointCloud::UpdateInfo()
{
    // 注意不要动态修改点云中的顶点，因为包围盒不会实时更新，导致下面的平移会出现问题
    m_info.size = m_points.size();
    m_info.modelMat = Transform::Translate(m_info.centroid - m_info._centroid);

    // 根据状态设置颜色
    if (m_info.status == AIS_Status::NONE)
        m_info.color = {1, 1, 1, 1};
    else if (m_info.status == AIS_Status::HANG)
        m_info.color = {0, 0, 1, 1};
    else if (m_info.status == AIS_Status::TOUCH)
        m_info.color = {0, 1, 0, 1};
}

CAGD::AIS_Type CAGD::AIS_PointCloud::GetType() const
{
    return AIS_Type::POINTCLOUD;
}

std::vector<CAGD::BPnt> &CAGD::AIS_PointCloud::GetPoints()
{
    return m_points;
}